﻿using Mirror;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WeaponSlot : Slot
{
    public enum FireMode 
    {
        WEAPON_MODE_MANUAL,
        WEAPON_MODE_AUTO,
        WEAPON_MODE_DISABLE,
    };
    public float AngleRangeP { get { return AngleRange * m_WeaponAngleMultiply; } }

    public bool m_Firing = false;
    public string FixedWeapon;
    public string PerloadWeapon;
    public int WeaponGroup = 1;
    public Vector3 ForwardDirection = new Vector3(0, 1, 0);
    public Vector3 CurrentWeaponDirection;
    public Vector3 TargetPosition { set
        {
            m_TargetPosition = value;
            m_TargetPosition.z = 0;
        } 
        get { return m_TargetPosition; }
    }
    Vector3 m_TargetPosition;
    public GameObject Target;
    public GameObject TargetHighPriority;
    public float AngleRange = 180;
    public float m_TargetAngle =0 ;
    public float m_Angle = 0;
    public Weapon.Level m_Level = Weapon.Level.LEVEL_SMALL;
    public Weapon.Speciality m_Speciality = Weapon.Speciality.POINT_DEFENSE;
    public float ShutCooling = 111111110;//  开火冷却时间
    public bool m_FireReady = true;
    public Weapon m_Weapon;
    public bool m_ForceTraceTarget = false;

    public bool m_FireLicense = true;
    public Callback OnFireCallback;
    public bool m_HasAirplant = false;
    Ship m_ArmShip;

    public float ShotVelocityMultiply { 
        set { 
            m_ShotVelocityMultiply = value;
            if (m_Weapon != null)
                m_Weapon.m_ShotVelocityMultiply = m_ShotVelocityMultiply;
        } 
        get { return m_ShotVelocityMultiply; }
    }
    public float ShotRangeMultiply
    {
        set
        {
            m_ShotRangeMultiply = value;
            if (m_Weapon != null)
            {
                m_Weapon.m_ShotRangeMultiply = m_ShotRangeMultiply;
                GenerateRangeLine();
            }
        }
        get { return m_ShotRangeMultiply; }
    }
    public float DamageMultiply
    {
        set
        {
            m_DamageMultiply = value;
            if (m_Weapon != null)
                m_Weapon.m_DamageMultiply = m_DamageMultiply;
        }
        get { return m_DamageMultiply; }
    }

    public float m_DamageMultiply = 1;
    public float m_ShotRangeMultiply = 1;
    public float m_ShotVelocityMultiply = 1;
    public float m_WeaponAngleMultiply = 1;

    float m_ArmAngleDeffent=11110;
    int m_LoseTargetCount=0;
    int m_LoseTargetMax = 3;
    public bool ShowRange { 
        get { return m_ShowRange; }
        set {
            m_ShowRange = value;
            if (RangeRender)
                RangeRender.SetActive(m_ShowRange);
            }
    }
    public FireMode FireMode2 {
        set {
            m_FireMode = value;
        }
        get { return m_FireMode; }
    }
    public bool m_ShowRange = false;
    public bool m_IsUse = false;//  是否是当前武器组
    public FireMode m_FireMode = FireMode.WEAPON_MODE_AUTO;
    GameObject RangeRender;


    private void Awake()
    {
        CurrentWeaponDirection = transform.up;
    }
    void Start()
    {
        hasFixedWeapon();
        //Weapon weapon;
        //if(m_Level == Weapon.Level.LEVEL_SMALL)
        //{
        //    float randomValue = Random.Range(0f, 1f);
        //    if (randomValue > 0.5)
        //        weapon = new MissileStandard01();
        //    else
        //        weapon = new LightMachineGun();
        //    switchWeapon(weapon);
        //}
        //else
        //{
        //    weapon = new AutoGunnery();
        //    switchWeapon(weapon);
        //}

    }

    // Update is called once per frame
    protected override void Update()
    {
        base.Update();
        if (null == m_Weapon)
            return;
        m_Weapon.update();

        //  同步角度
        var forward = transform.rotation * ForwardDirection;
        var resultRotation = Quaternion.AngleAxis(m_Angle, Vector3.forward);
        CurrentWeaponDirection = resultRotation * forward;
        if (EmiterObject)
            EmiterObject.transform.localRotation = resultRotation;


        //  开火冷却
        float shotVelocity = m_Weapon.ShutVelocity;
        if(m_Ship)
            shotVelocity /= m_Ship.ShotVelocityMutiple;
        ShutCooling += Time.deltaTime;
        if (m_FireReady == false && ShutCooling >  shotVelocity)
        {
            m_FireReady = true;
            ShutCooling = 0;
        }

        if (UtilsGame.IsOnline() && m_Ship && !UtilsGame.IsServer(m_Ship.gameObject))
        {
            //   同步服务器的角度，平滑
            float offsetAngle2 = m_Weapon.TurnSpeed * Time.deltaTime;
            if (m_Angle > m_TargetAngle)
            {
                m_Angle -= Mathf.Clamp(offsetAngle2, 0, m_Angle - m_TargetAngle);
            }
            else if(m_Angle < m_TargetAngle)
            {
                m_Angle += Mathf.Clamp(offsetAngle2, 0, m_TargetAngle-m_Angle);
            }
            if (m_Firing)
                FireOnlyEffect();
            return;
        }
        if (TargetPosition == new Vector3(0, 0, 0))
            return;

        //  为武器瞄准到鼠标方向
        var targetDifference = TargetPosition - transform.position;
        var targetDirection = targetDifference.normalized;

        m_ArmAngleDeffent = Vector3.Angle(CurrentWeaponDirection, targetDirection);
        if (m_ArmAngleDeffent < 1)
            return;

        //  如果目标方向和武器方向不在同一边，则巴拉巴拉
        float lr = Vector3.Cross(CurrentWeaponDirection, targetDirection).z;
        float targetSide = Vector3.Cross(forward, targetDirection).z;
        float weaponSide = Vector3.Cross(forward, CurrentWeaponDirection).z;

        if (weaponSide * targetSide < 0 &&
            AngleRangeP >= 180 && 
            Vector3.Angle(forward, targetDirection) + Vector3.Angle(forward, CurrentWeaponDirection) > 180)
        {
            m_ArmAngleDeffent = 360 - m_ArmAngleDeffent;
            lr = -lr;
        }

        float offsetAngle = m_Weapon.TurnSpeed * Time.deltaTime;
        if (offsetAngle > Mathf.Abs(m_ArmAngleDeffent))
            offsetAngle = Mathf.Abs(m_ArmAngleDeffent);
        if (lr >= 0)
            m_Angle += offsetAngle;
        else
            m_Angle -= offsetAngle;

        m_Angle = Mathf.Clamp(m_Angle, -AngleRangeP / 2, AngleRangeP / 2);
    }

    private void FixedUpdate()
    {
        if (null == m_Weapon ||
            (m_IsUse == true && (m_Ship && m_Ship.m_AutoFire2 == false)))
            return;
        /// 攻击模式
        if (m_FireMode != FireMode.WEAPON_MODE_AUTO)
            return;
        GameObject target = Target;
        if(TargetHighPriority != null)
            target = TargetHighPriority;
        if (null == target)
            return;


        m_Firing = false;
        bool inRange = false;
        if(target)
            inRange = checkInRange(target.transform.position);

        if(m_Weapon as UAV != null)
        {
            fire();
            inRange = true;
        }

        //  如果丢失目标，则将目标置为空
        if (((m_Ship && target == m_Ship.gameObject) || !inRange) &&
            !m_ForceTraceTarget)
        {
            m_LoseTargetCount++;
            if(m_LoseTargetCount > m_LoseTargetMax)
            {
                m_LoseTargetCount = 0;
                if(TargetHighPriority != null)
                {
                    TargetHighPriority = null;
                }
                else if(Target != null)
                {
                    Target = null;
                }
            }
            return;
        }
        arm(target.transform.position);
        if (m_ArmAngleDeffent < 5 && inRange)
        {
            fire();
            m_Firing = true;
        }

    }

    public bool checkInRange(Vector3 position)
    {
        var forward = transform.rotation * ForwardDirection;
        var targetDifference = position - transform.position;
        if (!CheckInAngle(position))
            return false;

        float targetPositionDistance = targetDifference.magnitude;
        if (targetPositionDistance > m_Weapon.ShutRange + 1)
        {
            return false;
        }
        return true;
    }
    public bool CheckInAngle(Vector3 position)
    {
        var forward = transform.rotation * ForwardDirection;
        var targetDifference = position - transform.position;
        var targetDirection = targetDifference.normalized;
        var angle = Vector3.Angle(forward, targetDirection);
        if (angle > AngleRangeP / 2)
        {
            return false;
        }
        return true;

    }
    void OnRenderObject()
    {
        return;
        //if (m_Weapon == null)
        //    return;
        //var resultDirection = transform.rotation * ForwardDirection;
        //resultDirection = Quaternion.AngleAxis(AngleRangeP / 2, new Vector3(0, 0, 1)) * resultDirection;

        //var currentPositionInScreen = Camera.current.WorldToScreenPoint(transform.position);
        //currentPositionInScreen.x = currentPositionInScreen.x / Camera.current.pixelWidth;
        //currentPositionInScreen.y = currentPositionInScreen.y / Camera.current.pixelHeight;

        //GL.PushMatrix(); //保存当前Matirx  
        //GL.LoadOrtho();  
        //GL.Begin(GL.LINES);
        //GL.Color(new Color(0.4f, 0.4f, 0.1f, 0.5f));
        //GL.Vertex3(currentPositionInScreen.x, currentPositionInScreen.y, 0);

        //for(int i=0; i<AngleRangeP; ++i)
        //{
        //    resultDirection = Quaternion.AngleAxis(1, new Vector3(0, 0, -1)) * resultDirection;
        //    resultDirection = resultDirection.normalized;
        //    var targetPosition = Camera.current.WorldToScreenPoint(transform.position + resultDirection * m_Weapon.ShutRange);
        //    targetPosition.x = targetPosition.x / Camera.current.pixelWidth;
        //    targetPosition.y = targetPosition.y / Camera.current.pixelHeight;
        //    GL.Vertex3(targetPosition.x, targetPosition.y, 0);
        //}
        //GL.Vertex3(currentPositionInScreen.x, currentPositionInScreen.y, 0);
        //GL.End();

        //GL.Begin(GL.LINES);
        //GL.Color(new Color(0.4f, 0.4f, 0.1f, 0.5f));
        //var currentDirectionPosition = Camera.current.WorldToScreenPoint(transform.position + CurrentWeaponDirection);
        //currentDirectionPosition.x = currentDirectionPosition.x / Camera.current.pixelWidth;
        //currentDirectionPosition.y = currentDirectionPosition.y / Camera.current.pixelHeight;
        //GL.Vertex3(currentPositionInScreen.x, currentPositionInScreen.y, 0);
        //GL.Vertex3(currentDirectionPosition.x, currentDirectionPosition.y, 0);
        //GL.End();
        //GL.PopMatrix();//读取之前的Matrix  


    }

    public void arm(Vector3 position)
    {
        TargetPosition = position;
    }
    public void ArmShip(Ship ship)
    {
        m_ArmShip = ship;
        if(m_Weapon != null)
            m_Weapon.ArmShip = ship;
        if (ship == null)
            return;

        UAV uav = m_Weapon as UAV;
        if (uav != null)
        {
            uav.ArmShip(ship);
        }
    }
    public void FireOnlyEffect()
    {
        if (null == m_Weapon ||
            !gameObject.activeSelf ||
            m_FireLicense == false ||
            (m_Ship && !m_Ship.m_FireLicense) )
        {
            return;
        }

        if (m_Ship)
            m_Weapon.FireRequst(m_Ship.gameObject, this, transform.position, CurrentWeaponDirection);
        else
            m_Weapon.FireRequst(null, this, transform.position, CurrentWeaponDirection);

        if (m_FireReady == false)
            return;

        if (m_Ship)
            m_Weapon.FireOnlyEffect(m_Ship.gameObject, this, transform.position, CurrentWeaponDirection);
        else
            m_Weapon.FireOnlyEffect(null, this, transform.position, CurrentWeaponDirection);

        m_FireReady = false;
        ShutCooling = 0;
    }
    public void fire()
    {
        if (null == m_Weapon ||
            !gameObject.activeSelf ||
            m_FireLicense == false ||
            (m_Ship && !m_Ship.m_FireLicense))
        {
            return;
        }

        if (m_Ship)
            m_Weapon.FireRequst(m_Ship.gameObject, this, transform.position, CurrentWeaponDirection);
        else
            m_Weapon.FireRequst(null, this, transform.position, CurrentWeaponDirection);
        if (m_FireReady == false)
            return;

        if(m_Weapon.m_IsCanShot)
        {
            FlyItem flyItem = null;
            if (m_Ship)
                flyItem = m_Weapon.Fire(m_Ship.gameObject, this, transform.position, CurrentWeaponDirection);
            else
                flyItem = m_Weapon.Fire(null, this, transform.position, CurrentWeaponDirection);
            var missleFunction = flyItem as MissileFunction;
            if(missleFunction != null && m_ArmShip)
            {
                missleFunction.m_Target = m_ArmShip.gameObject;
            }
            m_FireReady = false;
            ShutCooling = 0;
            if(OnFireCallback != null)
                OnFireCallback();
        }
    }

    //  检查是否是固定的武器
    public bool hasFixedWeapon()
    {
        if (FixedWeapon != "")
        {
            if(m_Weapon == null)
                switchWeapon(ItemFactory.Instance.createItem(FixedWeapon) as Weapon, true);
            return true;
        }
        return false;
    }
    public bool equipPerloadWeapon()
    {
        if (PerloadWeapon != "")
        {
            if(m_Weapon == null)
                switchWeapon(ItemFactory.Instance.createItem(PerloadWeapon) as Weapon, true);
            return true;
        }
        return false;
    }

    public void switchWeapon(Weapon weapon, bool syncRenderSort = true)
    {
        if (EmiterObject)
            Destroy(EmiterObject);

        if (null == weapon)
        {
            m_Weapon = null;
            return;
        }
        if (weapon.m_Level > m_Level)
        {
            return;
        }
        m_Weapon = weapon;
        m_Weapon.m_DamageMultiply = m_DamageMultiply;
        m_Weapon.m_ShotRangeMultiply = m_ShotRangeMultiply;
        m_Weapon.m_ShotVelocityMultiply = m_ShotVelocityMultiply;

        m_Weapon.Init(m_Ship, this);
        try
        {

            EmiterObject = Instantiate(Resources.Load<GameObject>(m_Weapon.WeaponResource)) as GameObject;
            EmiterObject.transform.SetParent(transform, false);
            if (syncRenderSort && EmiterObject.GetComponent<SpriteRenderer>())
            {
                EmiterObject.GetComponent<SpriteRenderer>().sortingLayerID = gameObject.GetComponent<SpriteRenderer>().sortingLayerID;
                EmiterObject.GetComponent<SpriteRenderer>().sortingOrder = gameObject.GetComponent<SpriteRenderer>().sortingOrder+1;
            }
        }
        catch
        {
            Debug.LogError("not found weapon emitter resouces: "+ m_Weapon.WeaponResource);
        }
        GenerateRangeLine();
    }

    void GenerateRangeLine()
    {
        /// 跟据新的武器生成范围线
        if (RangeRender == null)
        {
            Object obj = Resources.Load<GameObject>("Perfabs/Line");
            RangeRender = Instantiate(obj) as GameObject;
            RangeRender.transform.SetParent(transform, false);
        }
        RangeRender.SetActive(m_ShowRange);
        RangeRender.transform.localScale = new Vector3(1 / transform.localScale.x, 1 / transform.localScale.y, 1 / transform.localScale.z);
        LineRenderer line = RangeRender.GetComponent<LineRenderer>();

        var resultDirection = ForwardDirection;
        resultDirection = Quaternion.AngleAxis(AngleRangeP / 2, new Vector3(0, 0, 1)) * resultDirection;
        List<Vector3> points = new List<Vector3>();
        points.Add(Vector3.zero);

        for (int i = 0; i < AngleRangeP; ++i)
        {
            resultDirection = Quaternion.AngleAxis(1, new Vector3(0, 0, -1)) * resultDirection;
            resultDirection = resultDirection.normalized;

            points.Add(resultDirection * m_Weapon.ShutRange);
        }
        line.positionCount = points.Count;
        line.SetPositions(points.ToArray());
    }
}
